package vn.edu.saigontech.ncms.web.study;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import vn.edu.saigontech.ncms.model.info.AbstractReceipt;
import vn.edu.saigontech.ncms.model.info.Offering;
import vn.edu.saigontech.ncms.model.info.OfferingMember;
import vn.edu.saigontech.ncms.model.info.Teacher;
import vn.edu.saigontech.ncms.model.program.ProgramType;
import vn.edu.saigontech.ncms.model.result.FinalTest;
import vn.edu.saigontech.ncms.model.result.MakeUpTest;
import vn.edu.saigontech.ncms.service.FinalTestService;
import vn.edu.saigontech.ncms.service.MakeUpTestService;
import vn.edu.saigontech.ncms.service.OfferingMemberService;
import vn.edu.saigontech.ncms.service.OfferingService;
import vn.edu.saigontech.ncms.service.UserService;
import vn.edu.saigontech.ncms.util.Checker;
import vn.edu.saigontech.ncms.util.CollectionUtil;
import vn.edu.saigontech.ncms.util.DateUtil;
import vn.edu.saigontech.ncms.util.ImportExport;
import vn.edu.saigontech.ncms.vo.CertificateReportItem;
import vn.edu.saigontech.ncms.web.BaseAction;

@SuppressWarnings("serial")
public class FinalTestAction extends BaseAction {

	private Long id;
	private Long receiptId;
	private Long offeringId;

	private Long[] ids;
	private Double[] listenings;
	private Double[] pronunciations;
	private Double[] speakings;
	private Double[] grammars;
	private Double[] readings;
	private Double[] writings;
	private String[] comments;

	// Make-up Test
	private Long finalTestId;
	private String date;
	private Double writtenScore;
	private Double speakingScore;
	private Double listeningScore;
	private Double pronunciationScore;
	private Double grammarScore;
	private Double readingScore;
	private String comment;
	private String receiptNo;
	private Double fee;
	private Long cashierId;

	public String list() {
		Offering offering = OfferingService.INSTANCE.findById(this.offeringId);
		Collection<OfferingMember> members = OfferingMemberService.INSTANCE
				.findByOfferingId(this.offeringId);

		REQUEST().setAttribute("offering", offering);
		REQUEST().setAttribute("offeringMembers", members);
		return SUCCESS;
	}

	public String edit() {
		Offering offering = OfferingService.INSTANCE.findById(this.offeringId);
		for (int i = 0; i < this.ids.length; i++) {
			FinalTest finalTest = FinalTestService.INSTANCE
					.findById(this.ids[i]);
			if (!finalTest.checkIsMakeUp()) {
				offering.getFinalGradeDetail().injectGrade(finalTest,
						listenings, speakings, grammars, readings, writings,
						pronunciations, i);
				finalTest.setComment(this.comments[i]);
				FinalTestService.INSTANCE.persist(finalTest);
			}
		}
		this.addLoggingDetail(BaseAction.EDIT, "logging.final.edit", offering
				.getName());
		return SUCCESS;
	}

	public String showReport() {
		Collection<OfferingMember> members = OfferingMemberService.INSTANCE
				.findByOfferingId(this.offeringId, true);
		boolean noted = false;
		Iterator<OfferingMember> iterator = members.iterator();
		while (iterator.hasNext() && !noted) {
			String comment = iterator.next().getMidtermTest().getComment();
			if (comment != null)
				if (comment.length() > 10) {
					noted = true;
				}
		}
		Offering offering = OfferingService.INSTANCE.findById(this.offeringId);
		boolean ge = offering.getLevel().getProgram().getProgramType().equals(
				ProgramType.GE);

		REQUEST().setAttribute("noted", noted);
		REQUEST().setAttribute("ge", ge);
		REQUEST().setAttribute("offering", offering);
		REQUEST().setAttribute("offeringMembers", members);

		this.addLoggingDetail(BaseAction.REPORT, "logging.final.report1",
				offering.getName());
		return SUCCESS;
	}

	@Deprecated
	public String showOldReport() {
		REQUEST().setAttribute("offering",
				OfferingService.INSTANCE.findById(this.offeringId));
		REQUEST().setAttribute(
				"offeringMembers",
				OfferingMemberService.INSTANCE
						.findOldPassedByOfferingId(this.offeringId));
		return SUCCESS;
	}

	@Deprecated
	public String showOldScoreReport() {
		REQUEST().setAttribute("offering",
				OfferingService.INSTANCE.findById(this.offeringId));
		REQUEST().setAttribute(
				"offeringMembers",
				OfferingMemberService.INSTANCE
						.findOldPassedByOfferingId(this.offeringId));
		return SUCCESS;
	}

	@Deprecated
	public String showOldCertificate() throws Exception {
		Collection<CertificateReportItem> reportItems = OfferingMemberService.INSTANCE
				.issueOldCertificate(this.offeringId);
		RESPONSE().setContentType("application/pdf");
		RESPONSE().setHeader(
				"Content-disposition",
				"attachment; filename=\"" + "Class" + this.offeringId
						+ ".pdf\"");
		ImportExport.exportToPdfStream("certificate.jasper", null, reportItems,
				RESPONSE().getOutputStream());
		return NONE;
	}

	public String printTeachers(Collection<Teacher> teachers) {
		List<String> result = new ArrayList<String>();
		for (Teacher teacher : teachers) {
			result.add(this.i18n(teacher.getTitle().getKey()) + " "
					+ teacher.getFirstName());
		}
		return CollectionUtil.toString(result, " & ");
	}

	// CUONGPC
	public String listMakeUpTest() {
		Offering offering = OfferingService.INSTANCE.findById(this.offeringId);
		List<FinalTest> tests = offering.getMakeUpTests();
		if (tests.isEmpty())
			return ADD;
		boolean ge = offering.getLevel().getProgram().getProgramType().equals(
				ProgramType.GE);
		REQUEST().setAttribute("ge", ge);
		REQUEST().setAttribute("offering", offering);
		return SUCCESS;
	}

	public String showAddMakeUpTest() {
		Offering offering = OfferingService.INSTANCE.findById(this.offeringId);
		Set<AbstractReceipt> receipts = offering.getOfferingReceipts();
		List<AbstractReceipt> ret = new ArrayList<AbstractReceipt>();
		for (AbstractReceipt receipt : receipts) {
			FinalTest test = receipt.getMember().getFinalTest();
			if (!test.isAnyGradeInput() && !test.checkIsMakeUp()) {
				ret.add(receipt);
			}
		}
		boolean ge = offering.getLevel().getProgram().getProgramType().equals(
				ProgramType.GE);
		REQUEST().setAttribute("ge", ge);
		REQUEST().setAttribute("offering", offering);
		REQUEST().setAttribute("receipts", ret);
		REQUEST().setAttribute("cashiers",
				UserService.INSTANCE.findByRole("Consulting"));
		return SUCCESS;
	}

	public String infoMakeUpTest() {
		Offering offering = OfferingService.INSTANCE.findById(this.offeringId);
		FinalTest finalTest = FinalTestService.INSTANCE
				.findById(this.finalTestId);
		boolean ge = offering.getLevel().getProgram().getProgramType().equals(
				ProgramType.GE);
		REQUEST().setAttribute("ge", ge);
		REQUEST().setAttribute("offering", offering);
		REQUEST().setAttribute("finalTest", finalTest);
		REQUEST().setAttribute("receipt",
				finalTest.getOfferingMember().getReceipt());
		REQUEST().setAttribute("cashiers",
				UserService.INSTANCE.findByRole("Consulting"));
		return SUCCESS;
	}

	public String addMakeUpTest() {
		Offering offering = OfferingService.INSTANCE.findById(this.offeringId);
		MakeUpTest makeUpTest = new MakeUpTest();
		Date testDate = DateUtil.fromString(this.date, this.i18n(this
				.i18n("format.date")));
		makeUpTest.setMakeUpDate(testDate);
		makeUpTest.setReceiptNo(this.receiptNo);
		makeUpTest.setFee(this.fee);
		makeUpTest.setCashier(UserService.INSTANCE.findById(this.cashierId));
		MakeUpTest entity = MakeUpTestService.INSTANCE.persist(makeUpTest);
		String student = "";
		if (!Checker.isNull(entity)) {
			FinalTest finalTest = FinalTestService.INSTANCE
					.findById(this.finalTestId);
			finalTest.setListening(this.listeningScore);
			boolean ge = offering.getLevel().getProgram().getProgramType()
					.equals(ProgramType.GE);
			if (ge) {
				finalTest.setPronunciation(this.pronunciationScore);
			}
			finalTest.setSpeaking(this.speakingScore);
			finalTest.setGrammar(this.grammarScore);
			finalTest.setReading(this.readingScore);
			finalTest.setWriting(this.writtenScore);
			finalTest.setComment(this.comment);
			finalTest.setMakeUp(true);
			finalTest.setMakeUpTest(entity);
			FinalTestService.INSTANCE.persist(finalTest);
			student = finalTest.getOfferingMember().getReceipt().getStudent()
					.getFullName();
		}
		this.addLoggingDetail(BaseAction.ADD, "logging.makeUp.add", student,
				offering.getName());
		return SUCCESS;
	}

	public String editMakeUpTest() {
		Offering offering = OfferingService.INSTANCE.findById(this.offeringId);
		FinalTest finalTest = FinalTestService.INSTANCE
				.findById(this.finalTestId);
		MakeUpTest makeUpTest = finalTest.getMakeUpTest();
		Date testDate = DateUtil.fromString(this.date, this.i18n(this
				.i18n("format.date")));
		makeUpTest.setMakeUpDate(testDate);
		makeUpTest.setReceiptNo(this.receiptNo);
		makeUpTest.setFee(this.fee);
		makeUpTest.setCashier(UserService.INSTANCE.findById(this.cashierId));
		MakeUpTest entity = MakeUpTestService.INSTANCE.persist(makeUpTest);
		String student = "";
		if (!Checker.isNull(entity)) {
			finalTest.setListening(this.listeningScore);
			boolean ge = offering.getLevel().getProgram().getProgramType()
					.equals(ProgramType.GE);
			if (ge) {
				finalTest.setPronunciation(this.pronunciationScore);
			}
			finalTest.setSpeaking(this.speakingScore);
			finalTest.setGrammar(this.grammarScore);
			finalTest.setReading(this.readingScore);
			finalTest.setWriting(this.writtenScore);
			finalTest.setComment(this.comment);
			finalTest.setMakeUp(true);
			finalTest.setMakeUpTest(entity);
			FinalTestService.INSTANCE.persist(finalTest);
			student = finalTest.getOfferingMember().getReceipt().getStudent()
					.getFullName();
		}
		this.addLoggingDetail(BaseAction.EDIT, "logging.makeUp.edit", student,
				offering.getName());
		return SUCCESS;
	}

	public String deleteMakeUpTest() {
		FinalTest finalTest = FinalTestService.INSTANCE
				.findById(this.finalTestId);
		Long makeUpId = finalTest.getMakeUpTest().getId();
		finalTest.setListening(null);
		finalTest.setPronunciation(null);
		finalTest.setSpeaking(null);
		finalTest.setGrammar(null);
		finalTest.setReading(null);
		finalTest.setWriting(null);
		finalTest.setMakeUp(null);
		finalTest.setMakeUp(null);
		finalTest.setMakeUpTest(null);
		FinalTest entity = FinalTestService.INSTANCE.persist(finalTest);
		if (!Checker.isNull(entity)) {
			MakeUpTestService.INSTANCE.deleteById(makeUpId);
		}
		String student = finalTest.getOfferingMember().getReceipt()
				.getStudent().getFullName();
		String offering = finalTest.getOfferingMember().getReceipt()
				.getOffering().getName();

		this.addLoggingDetail(BaseAction.DELETE, "logging.makeUp.delete",
				student, offering);
		return SUCCESS;
	}

	public String showSearchMakeUpTest() {
		return SUCCESS;
	}

	public String showReportMakeUpTest() {
		return SUCCESS;
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public Long getOfferingId() {
		return offeringId;
	}

	public void setOfferingId(Long offeringId) {
		this.offeringId = offeringId;
	}

	public Long getReceiptId() {
		return receiptId;
	}

	public void setReceiptId(Long receiptId) {
		this.receiptId = receiptId;
	}

	public Long[] getIds() {
		return ids;
	}

	public void setIds(Long[] ids) {
		this.ids = ids;
	}

	public Double[] getListenings() {
		return listenings;
	}

	public void setListenings(Double[] listenings) {
		this.listenings = listenings;
	}

	public Double[] getSpeakings() {
		return speakings;
	}

	public void setSpeakings(Double[] speakings) {
		this.speakings = speakings;
	}

	public Double[] getReadings() {
		return readings;
	}

	public void setReadings(Double[] readings) {
		this.readings = readings;
	}

	public Double[] getWritings() {
		return writings;
	}

	public void setWritings(Double[] writings) {
		this.writings = writings;
	}

	public String[] getComments() {
		return comments;
	}

	public void setComments(String[] comments) {
		this.comments = comments;
	}

	public Double[] getGrammars() {
		return grammars;
	}

	public void setGrammars(Double[] grammars) {
		this.grammars = grammars;
	}

	public String getDate() {
		return date;
	}

	public void setDate(String date) {
		this.date = date;
	}

	public Double getWrittenScore() {
		return writtenScore;
	}

	public void setWrittenScore(Double writtenScore) {
		this.writtenScore = writtenScore;
	}

	public Double getSpeakingScore() {
		return speakingScore;
	}

	public void setSpeakingScore(Double speakingScore) {
		this.speakingScore = speakingScore;
	}

	public Double getListeningScore() {
		return listeningScore;
	}

	public void setListeningScore(Double listeningScore) {
		this.listeningScore = listeningScore;
	}

	public Double getGrammarScore() {
		return grammarScore;
	}

	public void setGrammarScore(Double grammarScore) {
		this.grammarScore = grammarScore;
	}

	public Double getReadingScore() {
		return readingScore;
	}

	public void setReadingScore(Double readingScore) {
		this.readingScore = readingScore;
	}

	public String getComment() {
		return comment;
	}

	public void setComment(String comment) {
		this.comment = comment;
	}

	public String getReceiptNo() {
		return receiptNo;
	}

	public void setReceiptNo(String receiptNo) {
		this.receiptNo = receiptNo;
	}

	public Double getFee() {
		return fee;
	}

	public void setFee(Double fee) {
		this.fee = fee;
	}

	public Long getCashierId() {
		return cashierId;
	}

	public void setCashierId(Long cashierId) {
		this.cashierId = cashierId;
	}

	public Long getFinalTestId() {
		return finalTestId;
	}

	public void setFinalTestId(Long finalTestId) {
		this.finalTestId = finalTestId;
	}

	public Double getPronunciationScore() {
		return pronunciationScore;
	}

	public void setPronunciationScore(Double pronunciationScore) {
		this.pronunciationScore = pronunciationScore;
	}

	public Double[] getPronunciations() {
		return pronunciations;
	}

	public void setPronunciations(Double[] pronunciations) {
		this.pronunciations = pronunciations;
	}
}
